﻿using System;
using System.IO.Ports;
using System.Linq;
using System.Windows.Forms;
using oModbus;
using oModbus.Device;
using oModbus.Message;
using oModbus.Utility;

namespace Sample
{
    public partial class MasterForm : Form
    {
        public MasterForm()
        {
            InitializeComponent();
        }

        private void MasterForm_Load(object sender, EventArgs e)
        {
            comboBoxSerialPorts.Items.Clear();
            foreach (var port in SerialPort.GetPortNames())
            {
                comboBoxSerialPorts.Items.Add(port);
            }
            if (comboBoxSerialPorts.Items.Count > 0)
                comboBoxSerialPorts.SelectedIndex = 0;
            comboBoxParity.Items.Clear();
            comboBoxParity.Items.Add(Parity.None.ToString());
            comboBoxParity.Items.Add(Parity.Odd.ToString());
            comboBoxParity.Items.Add(Parity.Even.ToString());
            comboBoxParity.Items.Add(Parity.Mark.ToString());
            comboBoxParity.Items.Add(Parity.Space.ToString());
            comboBoxParity.SelectedIndex = 0;
            comboBoxDataBits.SelectedIndex = 0;
            comboBoxStopBits.SelectedIndex = 0;
            BtnConnect.Enabled = true;
            BtnDisconnect.Enabled = false;
            comboBoxBaudRate.SelectedIndex = 1;
        }

        private void BtnConnect_Click(object sender, EventArgs e)
        {
            SerialPort port = new SerialPort(comboBoxSerialPorts.Text)
            {
                BaudRate = Convert.ToInt32(comboBoxBaudRate.Text),
                DataBits = 8,
                Parity = Parity.None,
                StopBits = StopBits.One
            };
            switch (comboBoxStopBits.Text)
            {
                case "None":
                    port.StopBits = StopBits.None;
                    break;
                case "1":
                    port.StopBits = StopBits.One;
                    break;
                case "1.5":
                    port.StopBits = StopBits.OnePointFive;
                    break;
                case "2":
                    port.StopBits = StopBits.Two;
                    break;

            }
            switch (comboBoxStopBits.Text)
            {
                case "None":
                    port.Parity = Parity.None;
                    break;
                case "Odd":
                    port.Parity = Parity.Odd;
                    break;
                case "Even":
                    port.Parity = Parity.Even;
                    break;
                case "Mark":
                    port.Parity = Parity.Mark;
                    break;
                case "Space":
                    port.Parity = Parity.Space;
                    break;
            }
            var temp = new SerialTransmission(port);
            if (temp.Open())
            {
                _master = new ModbusMaster(1, temp);
                //   _master.SendMessageEvent += _slave_SendMessageEvent;     public event Action<byte[]> SendMessageEvent;
                _master.ReceivedMessageEvent += _transmission_ReceivedMessageEvent;
                _master.SendMessageEvent += _slave_SendMessageEvent;
                _master.ReadCoilEvent += _master_ReadCoilEvent;
                _master.ReadHoldRegisterEvent += _master_ReadHoldRegisterEvent;
                BtnConnect.Enabled = false;
                BtnDisconnect.Enabled = true;
            }
            else
            {
                MessageBox.Show(@"打开失败");
            }
        }

        private void _master_ReadHoldRegisterEvent(ReadHoldRegisterResponse obj)
        {
            if (txtInfo.InvokeRequired)
            {
                //后端线程向主线程记日志
                Invoke(new Action<ReadHoldRegisterResponse>(_master_ReadHoldRegisterEvent), obj);
            }
            else
            {

                temperature_lbl.Text = "温度：" +(obj.RegisterState[0]+ (double)obj.RegisterState[1]/100) + "湿度：" + (obj.RegisterState[2] + (double)obj.RegisterState[3] / 100);


                //  txtInfo.Text += title + data.GetHexString() + Environment.NewLine;

            }
        }

        private void _slave_SendMessageEvent(byte[] data)
        {
            Show("发送：", data);
        }
        private void _master_ReadCoilEvent(ReadCoilResponse obj)
        {
            ReadCoilResponse response = new ReadCoilResponse(_master.SlaveId, new byte[] { 0x01, 02 }.ToList());
            _master.Send(response);
        }

        private ModbusMaster _master;
        private void _transmission_ReceivedMessageEvent(byte[] data)
        {
            Show("接受：", data);
        }

        private void Show(string title, byte[] data)
        {
            if (txtInfo.InvokeRequired)
            {
                //后端线程向主线程记日志
                Invoke(new Action<string, byte[]>(Show), title, data);
            }
            else
            {
                //主线程直接记日志
                if (ckbHex.Checked)
                {
                    txtInfo.Text += title + data.GetHexString() + Environment.NewLine;
                }
                else
                {
                    txtInfo.Text += title + data.GetHexString() + Environment.NewLine;
                }
            }
        }

        private void BtnDisconnect_Click(object sender, EventArgs e)
        {
            _master.Close();
            _master.ReceivedMessageEvent -= _transmission_ReceivedMessageEvent;

            BtnConnect.Enabled = true;
            BtnDisconnect.Enabled = false;
        }

        private void BtnSend_Click(object sender, EventArgs e)
        {
            ushort startAddress = 100;
            ushort number = 5;

            // var request = new ReadDiscreteInputRequest(1, startAddress, number);
            var request = new WriteSingleCoilRequest(1, startAddress, number);
            //byte[] data = request.PackingMessage();
            //ReadCoilRequest res = new ReadCoilRequest(data); 
            _master.Send(request);
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            txtInfo.Text = "";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            _master.Send(new WriteSingleCoilRequest(1, 0, 0xff));
        }

        private void button2_Click(object sender, EventArgs e)
        {
            _master.Send(new WriteSingleCoilRequest(1, 0, 0));
        }

        private void button4_Click(object sender, EventArgs e)
        {
            _master.Send(new WriteSingleCoilRequest(1, 1, 0xff));
        }

        private void button3_Click(object sender, EventArgs e)
        {
            _master.Send(new WriteSingleCoilRequest(1, 1, 0));
        }

        private void read_temperature_btn_Click(object sender, EventArgs e)
        {
            _master.Send(new ReadHoldRegisterRequest(1, 0, 2));
        }
    }
}
